package com.pbd.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LatLngCallback;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.geom.Point;
import com.google.gwt.maps.client.geom.Size;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;

public class GoogleMap extends Composite {

	private LatLng gopoint = null;

	private Geocoder geocoder;

	private static final TextBox latLabel = new TextBox();
	private static final TextBox lngLabel = new TextBox();;

	private MapWidget map;
	private HorizontalPanel horiz = new HorizontalPanel();;
	//private GooglePopup googlePopup;
	private Panel panel;
	public GoogleMap(final String width, final String height, final String area, final Double latitude, final Double longitude,  final AsyncCallback asyncCallbackMain) {
		panel = new FlowPanel();
		
//		panel.setHeight("350px");
//		panel.setWidth("400px");
		
		panel.setHeight(height);
		panel.setWidth(width);
		
		final FormPanel form = new FormPanel();
		//form.setHeight("300px");
		//form.setWidth("250px");
		form.setAction("#");

		/*
		 * ABQIAAAAu-
		 * SU5caRyWQZQMDtPk_j9BRapji81OYxLgkLIC5OBwjJr9KkiBSyOMxozz3FbTAJTVW0E0nYB4eJoQ
		 * , AIzaSyAV519XmEHQ0C-kRuqlsLZ4g9Iy0XSJkXE
		 */
		Maps.loadMapsApi("", "2", false, new Runnable() {
			public void run() {
				if(latitude!=null && longitude!=null && latitude > 0.0 && longitude > 0.0){
					gopoint = LatLng.newInstance(latitude, longitude);
				}else{
					gopoint = LatLng.newInstance(13.0810, 80.2740);
				}
				Panel formElements = new FlowPanel();
				formElements.add(horiz);

				Button submit = new Button("Find Again!");
				submit.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						form.submit();
					}
				});
//				Button enlargButton = new Button("Show in Enlarge Map");
//
//				enlargButton.addClickHandler(new ClickHandler() {
//
//					@Override
//					public void onClick(ClickEvent event) {
//						// GooglePanel.this.hide();
//						googlePopup = new GooglePopup("", "", area, new AsyncCallback() {
//							@Override
//							public void onFailure(Throwable caught) {
//								caught.printStackTrace();
//							}
//
//							@Override
//							public void onSuccess(Object result) {
//								googlePopup.hide();
//								Map map = (Map) result;
//								if (map != null && map.size() > 1) {
//									Double latitude = (Double) map.get("Latitude");
//									Double longitude = (Double) map.get("Longitude");
//									LatLng point = LatLng.newInstance(latitude, longitude);
//									showAddressLanLon(point, area, asyncCallbackMain);
//								} else {
//									showAddressLanLon(gopoint, area, asyncCallbackMain);
//								}
//							}
//						});
//
//						googlePopup.center();
//					}
//				});
				formElements.add(submit);
				//formElements.add(enlargButton);
				form.add(formElements);
				form.addSubmitHandler(new SubmitHandler() {
					public void onSubmit(SubmitEvent event) {
						if(area!=null)
						showAddress(area, asyncCallbackMain);
						event.cancel();
					}
				});
				panel.add(form);

				if (gopoint != null) {
					map = new MapWidget(gopoint, 12);
					map.setScrollWheelZoomEnabled(true);
					map.setWidth("600px");
					map.setHeight("350px");
				}
				if (width != null && width.length() > 0) {
					map.setWidth(width);
				} else {
					//map.setWidth("250px");
				}
				if (height != null && height.length() > 0) {
					map.setHeight(height);

				} else {
					//map.setHeight("300px");
				}
				panel.add(map);
				HorizontalPanel horizontalPanel = new HorizontalPanel();

				horizontalPanel.add(submit);
				//horizontalPanel.add(enlargButton);
				panel.add(horizontalPanel);
				geocoder = new Geocoder();
				if(area!=null)
				showAddress(area, asyncCallbackMain);
			}
		});
		initWidget(panel);

	}

	public GoogleMap(final String add, final List area, final String type, final String width, final String height) {
		panel = new FlowPanel();
		final FormPanel form = new FormPanel();
		form.setAction("#");
		
//		panel.setHeight("350px");
//		panel.setWidth("400px");
		
		panel.setHeight(height);
		panel.setWidth(width);

		Maps.loadMapsApi("", "2", false, new Runnable() {
			public void run() {
				gopoint = LatLng.newInstance(13.0810, 80.2740);
				Panel formElements = new FlowPanel();
				formElements.add(horiz);

				Button submit = new Button("Find Again!");
				submit.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						form.submit();
					}
				});

				formElements.add(submit);
				form.add(formElements);
				form.addSubmitHandler(new SubmitHandler() {
					public void onSubmit(SubmitEvent event) {
						showAddressForString(add, area, type, width, height, new AsyncCallback() {

							@Override
							public void onFailure(Throwable caught) {
								caught.printStackTrace();
							}

							@Override
							public void onSuccess(Object result) {
								map = (MapWidget) result;
								panel.add(map);
								panel.add(form);
							}
						});
						event.cancel();
					}
				});

				HorizontalPanel horizontalPanel = new HorizontalPanel();

				horizontalPanel.add(submit);
				// horizontalPanel.add(okButton);
				// horizontalPanel.add(cancelButton);
				panel.add(horizontalPanel);
				geocoder = new Geocoder();
				showAddressForString(add, area, type,width, height, new AsyncCallback() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
					}

					@Override
					public void onSuccess(Object result) {
						if(panel.isAttached())
							panel.clear();
						map = (MapWidget) result;
						panel.add(map);
						panel.add(form);
					}
				});
			}
		});

		initWidget(panel);
	}

//	private void showAddress(String add, List area) {
//		map.setUIToDefault();
//		map.clearOverlays();
//
//		Icon icon = Icon.newInstance("http://labs.google.com/ridefinder/images/mm_20_red.png");
//		icon.setShadowURL("http://labs.google.com/ridefinder/images/mm_20_shadow.png");
//		icon.setIconSize(Size.newInstance(12, 20));
//		icon.setShadowSize(Size.newInstance(22, 20));
//		icon.setIconAnchor(Point.newInstance(6, 20));
//		icon.setInfoWindowAnchor(Point.newInstance(5, 1));
//
//		LatLngBounds bounds = map.getBounds();
//		LatLng southWest = bounds.getSouthWest();
//		LatLng northEast = bounds.getNorthEast();
//		double lngSpan = northEast.getLongitude() - southWest.getLongitude();
//		double latSpan = northEast.getLatitude() - southWest.getLatitude();
//		MarkerOptions options = MarkerOptions.newInstance();
//		options.setIcon(icon);
//
//		int length = area == null ? 0 : area.size();
//		for (int i = 0; i < length; i++) {
//			List latLngList = (List) area.get(i);
//			int latLnglength = latLngList == null ? 0 : latLngList.size();
//			if (latLnglength != 2) {
//				throw new RuntimeException();
//			} else {
//
//				Double lan = Double.parseDouble(latLngList.get(0) + "");
//				Double lng = Double.parseDouble(latLngList.get(1) + "");
//				LatLng point = LatLng.newInstance(lan, lng);
//
//				map.addOverlay(new Marker(point, options));
//			}
//
//		}
//	}

	private void showAddressForString(String add, List dataList, String type, String width, String height, final AsyncCallback asyncCallback) {
		map = new MapWidget(LatLng.newInstance(13.0810, 80.2740), 12);
		
//		map.setSize("400px", "350px");
		map.setSize(width, height);
		map.setUIToDefault();

		map.setUIToDefault();
		map.clearOverlays();

		Icon icon = Icon.newInstance("http://labs.google.com/ridefinder/images/mm_20_red.png");
		icon.setShadowURL("http://labs.google.com/ridefinder/images/mm_20_shadow.png");
		icon.setIconSize(Size.newInstance(12, 20));
		icon.setShadowSize(Size.newInstance(22, 20));
		icon.setIconAnchor(Point.newInstance(6, 20));
		icon.setInfoWindowAnchor(Point.newInstance(5, 1));

		LatLngBounds bounds = map.getBounds();
		LatLng southWest = bounds.getSouthWest();
		LatLng northEast = bounds.getNorthEast();
		
//		double lngSpan = northEast.getLongitude() - southWest.getLongitude();
//		double latSpan = northEast.getLatitude() - southWest.getLatitude();
		
		final MarkerOptions options = MarkerOptions.newInstance();
		options.setIcon(icon);

		int length = dataList == null ? 0 : dataList.size();
		map.clearOverlays();
		for (int i = 0; i < length; i++) {
			if (type.equalsIgnoreCase("Address")) {
				final String latLngList = (String) dataList.get(i);
				System.out.println("=======================" + latLngList);
				geocoder.getLatLng(latLngList, new LatLngCallback() {
					public void onFailure() {
						System.err.println(latLngList + " not found");
					}

					public void onSuccess(final LatLng point) {
						map.setCenter(point, 3);
						map.addOverlay(new Marker(point, options));
					}

				});
			} else if (type.equalsIgnoreCase("LatLng")) {
				
				System.err.println("dataList size = " + dataList.size());
				
				final ArrayList valueList = (ArrayList) dataList.get(i);
				Double latitude = (Double) valueList.get(0);
				Double longitude = (Double) valueList.get(1);
				LatLng point = LatLng.newInstance(latitude, longitude);

				map.setCenter(point, 3);
				map.addOverlay(new Marker(point, options));

			}
		}
		asyncCallback.onSuccess(map);
	}

	private Panel buildLatLngPanel() {
		horiz.add(new Label("Lat:"));
		horiz.add(latLabel);
		horiz.add(new Label("Long:"));
		horiz.add(lngLabel);
		horiz.setSpacing(10);
		displayLatLng();
		return horiz;
	}

	private void displayLatLng() {
		NumberFormat fmt = NumberFormat.getFormat("#.0000000#");
		latLabel.setText((fmt.format(gopoint.getLatitude())));
		lngLabel.setText(fmt.format(gopoint.getLongitude()));
		buildLatLngPanel();
		horiz.clear();
		horiz.add(new Label("Lat:"));
		horiz.add(new Label((fmt.format(gopoint.getLatitude()))));
		horiz.add(new Label("Long:"));
		horiz.add(new Label(fmt.format(gopoint.getLongitude())));
		horiz.setSpacing(10);

	}

	private void showAddress(final String address, final AsyncCallback asyncCallback) {
		final InfoWindow info = map.getInfoWindow();

		geocoder.getLatLng(address, new LatLngCallback() {
			public void onFailure() {
				System.err.println(address + " not found");
			}

			public void onSuccess(final LatLng point) {
				final MarkerOptions options = MarkerOptions.newInstance();
				options.setDraggable(true);

				map.setCenter(point, 15);
				map.setUIToDefault();
				
				map.setGoogleBarEnabled(false);
				gopoint = point;
				final Marker marker = new Marker(point, options);
				marker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
					public void onDragEnd(MarkerDragEndEvent event) {
						gopoint = marker.getLatLng();
						info.open(marker, new InfoWindowContent(address + marker.getLatLng()));

						if (asyncCallback != null) {
							Map map = new HashMap();
							map.put("Latitude", gopoint.getLatitude());
							map.put("Longitude", gopoint.getLongitude());
							asyncCallback.onSuccess(map);
						}
					}
				});
				map.clearOverlays();
				map.addOverlay(marker);
				info.open(marker, new InfoWindowContent(address + marker.getLatLng()));
				if (asyncCallback != null) {
					Map map = new HashMap();
					map.put("Latitude", gopoint.getLatitude());
					map.put("Longitude", gopoint.getLongitude());
					asyncCallback.onSuccess(map);
				}
			}
		});
	}

	private void showAddressLanLon(final LatLng point, final String address, final AsyncCallback asyncCallback) {
		final InfoWindow info = map.getInfoWindow();
		final MarkerOptions options = MarkerOptions.newInstance();
		options.setDraggable(true);

		map.setCenter(point, 3);
		map.setUIToDefault();
		map.setGoogleBarEnabled(true);
		gopoint = point;
			
		
		final Marker marker = new Marker(point, options);
		marker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
			public void onDragEnd(MarkerDragEndEvent event) {
				gopoint = marker.getLatLng();
				info.open(marker, new InfoWindowContent(address + marker.getLatLng()));

				if (asyncCallback != null) {
					Map map = new HashMap();
					map.put("Latitude", gopoint.getLatitude());
					map.put("Longitude", gopoint.getLongitude());
					asyncCallback.onSuccess(map);
				}
			}
		});
		map.clearOverlays();
		map.addOverlay(marker);
		info.open(marker, new InfoWindowContent(address + marker.getLatLng()));
		if (asyncCallback != null) {
			Map map = new HashMap();
			map.put("Latitude", gopoint.getLatitude());
			map.put("Longitude", gopoint.getLongitude());
			asyncCallback.onSuccess(map);
		}
	}

	public LatLng getINDIA() {
		return gopoint;
	}

	public void setINDIA(LatLng india) {
		gopoint = india;
	}
}
